<?php defined('SYSPATH') or die('No direct script access.');

class Model_Category extends Model_Filter
{ 
    protected $_reload_on_wakeup = false; 
   
    public function get_categories($category, $width_breadcrumbs = true, $use_denormalization = true, $disable_cache = false)
    {
        $stat = array();
               
        $ids = array();
        $category_id = self::_get_category_id($category, $ids);
        
        if (!$disable_cache && $categories = Cache::instance()->get('catalog_categories_'.$category_id.'_'.$width_breadcrumbs)) {
            return $categories;
        }
        
        $isset_denormalized_data = null;
        if ($use_denormalization) {
            // Узнаем, используется ли денормализация
            $isset_denormalized_data = self::_isset_category_denormalized_data($category_id);   
        }
        
        if ($use_denormalization && $isset_denormalized_data) {
            $tmp_stat = self::_get_category_denormalized_data($category_id);    
        } else {
            $tmp_stat = DB::select('category_id', array(DB::expr('COUNT( * )'), 'count'))
                            ->from('products')
                            ->where('is_available', '=', 1);
                            
            if (is_array($ids) && count($ids) > 0) {
                $tmp_stat->where('category_id', 'IN', $ids);
            }
            
            $tmp_stat = $tmp_stat
                    ->group_by('category_id')
                    ->order_by('count', 'DESC')  
                    ->execute()
                    ->as_array();
        }
        
        $ids = array();
        foreach ($tmp_stat as $item) {
            $ids[] = $item['category_id'];
            $stat[$item['category_id']] = $item['count'];    
        }
        if (!count($ids)) {
            return array();    
        }
        $categories = array();
        $tmp_categories = ORM::factory('category')
                        ->where('id', 'IN', $ids);
                        
        if ($category_id) {
            $tmp_categories->where('parent_id', '=', $category_id);    
        } else {
            $tmp_categories->limit(15);    
        }
                        
        $tmp_categories = $tmp_categories
                            ->find_all()
                            ->as_array();
        foreach ($tmp_categories as $_category) {
            $_category = $_category->as_array(); 
            $categories[$_category['id']] = $_category;
            $categories[$_category['id']]['count'] = $stat[$_category['id']];            
        } 
        usort($categories, array(__CLASS__, '_compare'));
        
        $tree = array();
        if ($category_id) {     // есть категория, значит работаем с хлебными крошками
            if ($width_breadcrumbs) {
                $breadcrumbs = $category->get_breadcrumbs();
                
                $pointer = &$tree;
                foreach ($breadcrumbs as $_category) {
                    $_category = $_category->as_array();
                    $_category['items'] = array();
                    $pointer[$_category['id']] = $_category;
                    $pointer = &$pointer[$_category['id']]['items'];       
                } 
                
                $_category = $category->as_array();
                $_category['items'] = array();
                $pointer[$_category['id']] = $_category;
                $pointer = &$pointer[$_category['id']]['items'];
                
                foreach ($categories as $_category) {
                    $pointer[$_category['id']] = $_category;    
                }
            } else {
                $tree = $categories;
            } 
        } else {
            // TODO переделать по-умному =)
            $tree = $categories;    
        }
        
        Cache::instance()->set('catalog_categories_'.$category_id.'_'.$width_breadcrumbs, $tree);
        return $tree;                                
    }
    
    public function get_category_by_url($url)
    {
        $category = ORM::factory('category')->where('url', '=', $url)->find();
        if (!$category->loaded()) {
            throw new HTTP_Exception_404('Запись не найдена');      
        }
        return $category;
    }
    
    public function get_main_categories()
    {
        if ($categories = Cache::instance()->get('main_categories')) {
            return $categories;
        }
        
        $main_cats = array(1830, 1834, 1974, 1934, 1938);
        $categories = ORM::factory('category')
                        ->where('id', 'IN', $main_cats)
                        ->find_all()
                        ->as_array();
        
        Cache::instance()->set('main_categories', $categories);
        return $categories;
    }
    
    public function get_categories_tree()
    {
        if ($categories = Cache::instance()->get('categories_tree')) {
            return $categories;
        }
        
        // Максимум 3 уровня вложенноси, не придумываем ничего универсального
        $_first_row = $this->get_top_categories();
        $first_row = array();
        
        $ids = array();
        foreach ($_first_row as $category) {
            if ($category->id == 1776) {
                $ids[] = $category->id; 
                $first_row[$category->id] = $category->as_array();
                $first_row[$category->id]['active'] = false;
                $first_row[$category->id]['items']  = array();  
            }
        }
        $_second_row = $this->_get_categories_query()
                    ->where('parent_id', 'IN', $ids)
                    ->find_all();
        $second_row = array();
                    
        $ids = array();
        foreach ($_second_row as $category) {
            $ids[] = $category->id; 
            $second_row[$category->id] = $category->as_array();
            $second_row[$category->id]['active'] = false;
            $second_row[$category->id]['items']  = array();
        }
        $third_row = $this->_get_categories_query()
                    ->where('parent_id', 'IN', $ids)
                    ->order_by('name', 'ASC')   
                    ->find_all()
                    ->as_array();
                    
        foreach ($third_row as &$category) {
            $category = $category->as_array();
            $category['active'] = true;    
            
            $second_row[$category['parent_id']]['items'][] = $category;   
        }
        
        foreach ($second_row as &$category) {
            $first_row[$category['parent_id']]['items'][] = $category;    
        }
        
        Cache::instance()->set('categories_tree', $first_row);
        return $first_row;        
    }
    
    public function get_category_tree()
    {
        if ($categories = Cache::instance()->get('category_tree_'.$this->id)) {
            return $categories;
        }
        
        // Максимум 3 уровня вложенноси, не придумываем ничего универсального
        $_first_row = $this->_get_categories_query()
                    ->where('parent_id', '=', $this->id)
                    ->find_all();
        $first_row = array();
        
        $ids = array();
        foreach ($_first_row as $category) {
            $ids[] = $category->id; 
            $first_row[$category->id] = $category->as_array();
            $first_row[$category->id]['active'] = false;
            $first_row[$category->id]['items']  = array();  
        }
        if (count($ids)) {
            $_second_row = $this->_get_categories_query()
                        ->where('parent_id', 'IN', $ids)
                        ->find_all();
            $second_row = array();
                        
            $ids = array();
            foreach ($_second_row as $category) {
                $ids[] = $category->id; 
                $second_row[$category->id] = $category->as_array();
                $second_row[$category->id]['active'] = false;
                $second_row[$category->id]['items']  = array();
            }
            if (count($ids)) {
                $third_row = $this->_get_categories_query()
                            ->where('parent_id', 'IN', $ids)
                            ->order_by('name', 'ASC')   
                            ->find_all()
                            ->as_array();
                            
                foreach ($third_row as &$category) {
                    $category = $category->as_array();
                    $category['active'] = true;    
                    
                    $second_row[$category['parent_id']]['items'][] = $category;   
                }
            }
            
            foreach ($second_row as &$category) {
                $first_row[$category['parent_id']]['items'][] = $category;    
            }
        }
        
        Cache::instance()->set('category_tree_'.$this->id, $first_row);
        return $first_row;        
    }
    
    public function get_top_categories()
    {
        if ($categories = Cache::instance()->get('top_categories')) {
            return $categories;
        }
        $categories = $this->_get_categories_query()->where('parent_id', '=', 0)->order_by('rank', 'ASC')->find_all(); 
        Cache::instance()->set('top_categories', Model_Main::get_array($categories));
        return $categories;
    } 
    
    public function get_childs()
    {
        if ($categories = Cache::instance()->get('categories_'.$this->id)) {
            return $categories;
        }
        $categories = $this->_get_categories_query()->where('parent_id', '=', $this->id)->find_all();
        Cache::instance()->set('categories_'.$this->id, Model_Main::get_array($categories));
        return $categories;  
    }
    
    protected function _get_categories_query()
    {
        return ORM::factory('category');  
    }
    
    public function get_breadcrumbs()
    {
        if ($breadcrumbs = Cache::instance()->get('category_breadcrumbs_'.$this->id)) {
            return $breadcrumbs;
        }
        $breadcrumbs = array();
        $category_id = $this->parent_id;
        $old_category_id = $category_id;
        
        while ($category_id) {
            $category = ORM::factory('category', $category_id);
            $breadcrumbs[] = $category;   
            
            $category_id = $category->parent_id;
        }
        
        $breadcrumbs = array_reverse($breadcrumbs);
        Cache::instance()->set('category_breadcrumbs_'.$this->id, $breadcrumbs);
        return $breadcrumbs;    
    }
    
    public function get_categories_by_products($products)
    {
        $ids = array();
        foreach ($products as $product) {
            if (!isset($ids[$product->category_id])) {
                $ids[$product->category_id] = 0;    
            }
            $ids[$product->category_id]++;   
        }
        //arsort($ids);
        
        $categories  = array();
        if (!count($ids)) {
            return $categories;    
        }
        
        $_categories = ORM::factory('category')
                        ->where('id', 'IN', array_keys($ids))
                        ->find_all()
                        ->as_array();
        foreach ($_categories as $category) {
            $categories[$ids[$category->id]] = $category;    
        }
        krsort($categories);
                        
        return $categories;
    }
    
    public function get_big_categories()
    {
        return array(/*312, 1702, 1848, 2030, 2085, 2383, 313, 374, 1949, 2007, 2194, 2214, 2255, 2265, 1703,*/ 1729, /*1824, 1963,
            1989, 2176, 2314, 1849, 1872, 1923, 2160, 2031, 2043, 2054, 2061, 2077, 2086, 2095, 2111, 2119, 2126, 2384, 2400*/);
    }
    
    public function get_stemmed_categories()
    {
        function get_category_breadcrumbs($cat_id, &$cats)
        {
            $text = array();
            $cat = $cats[$cat_id];
            while ($cat['parent_id'] != 0) {
                $cat = $cats[$cat['parent_id']];
                $text[] = $cat['name'];
            }
            return implode(' ', $text);
        }
        
        $categories = ORM::factory('category')->find_all()->as_array(); 
        
        $_categories = array();     // для иерархии категорий
        foreach ($categories as $category) {
            $_categories[$category->id] = array(
                'id'        => $category->id,
                'parent_id' => $category->parent_id,
                'name'      => $category->name,
            );    
        }
        
        $stemmed_categories = array();
        foreach ($categories as $category) { 
            $data = array(
                'name'     => array(
                    'value'  => mb_strtolower(Model_Main::get_clean_name($category->nominative_form)),
                    'weight' => 2,
                ),
                /*'category' => array(
                    'value'  => mb_strtolower(Model_Main::get_clean_name(get_category_breadcrumbs($category->id, $_categories))),
                    'weight' => 0.5,
                ),*/
            );
            // название и иерархию категорий разбиваем на слова
            // лемматизация слов
            $category_words = $text = array();
            foreach ($data as $part) {
                $words  = explode(' ', $part['value']);
                $weight = $part['weight']; 
                foreach ($words as $word) {
                    if ($word) {
                        $word = Model_Stemmer::stem(trim($word));
                        $category_words[] = array(
                            'value'  => $word,
                            'weight' => $weight,
                        );
                        //$text[] = $word; 
                    }   
                }   
            }
            $stemmed_categories[$category->id] = array(
                'words'  => $category_words,
                //'text'   => implode(' ', $text),
                'object' => $category,
            );
        }
        return $stemmed_categories;
    }
}
